{
 "cells": [
  {
   "cell_type": "markdown",
   "source": [
    "# Python SDK request ZhipuAI GLM API\n",
    "\n",
    "**This tutorial is available in English and is attached below the Chinese explanation**\n",
    "\n",
    "本代码将带带领开发者熟悉如何使用 ZhipuAI  python 的 SDK 来对GLM-4模型进行请求，在本代码中，我展示了三种方式\n",
    "1. 同步请求\n",
    "2. 异步请求\n",
    "3. 流式请求\n",
    "三种请求方式的方法略有不同，在本代码中将会进行系统的介绍。\n",
    "\n",
    "This cookbook will lead developers to become familiar with how to use python's SDK to request the GLM-4 model. In this code, I show three ways\n",
    "1. Synchronous request\n",
    "2. Asynchronous request\n",
    "3. Streaming requests\n",
    "The three request methods are slightly different, and will be systematically introduced in this code."
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "446bb790af782d79"
  },
  {
   "cell_type": "markdown",
   "source": [
    "首先，我们需要配置 API Key，这个 API Key 可以在 [ZhipuAI API 平台申请](https://open.bigmodel.cn/) 。我们可以通过以下方式配置 API Key\n",
    "\n",
    "First, we need to configure the API Key. This API Key can be applied on [ZhipuAI API Platform](https://open.bigmodel.cn/). We can configure the API Key in the following ways"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "21629767cf7f59e6"
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "outputs": [],
   "source": [
    "import os\n",
    "from zhipuai import ZhipuAI\n",
    "\n",
    "os.environ[\"ZHIPUAI_API_KEY\"] = \"your api key\"\n",
    "client = ZhipuAI()\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-04-28T03:01:01.959873Z",
     "start_time": "2024-04-28T03:01:01.734820Z"
    }
   },
   "id": "558c314371522260"
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 1. Use synchronous request to request the model\n",
    "同步请求是最基本的请求方式，通过同步请求，我们可以直接获得模型的返回结果。我们仅需按照类似 OpenAI 的清求方式，填充参数，即可获得返回结果。\n",
    "\n",
    "Synchronous request is the most basic request method. Through synchronous request, we can directly obtain the return result of the model. We only need to fill in the parameters in a clearing method similar to OpenAI to get the returned results.\n",
    "\n",
    "\n",
    "<span style='color: red; font-weight: bold;'>⚠️ temperature 支持的范围为(0,1)，请确保温度参数设置的范围，您可以设置 `do_sample` 参数为 False 以实现温度为 0 的效果⚠️</span>\n",
    "<span style='color: red; font-weight: bold;'>⚠️ The supported range of temperature is (0,1), please ensure that the temperature parameter setting range is. You can set the `do_sample` parameter to False to achieve the effect of a temperature of 0.⚠️</span>"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "1d7c210cbf15238a"
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "取值范围是：(0.0, 1.0) 开区间，do_sample重写为:false（参数top_p temperture不生效）\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "temperature:0.0\n",
      "top_p:0.1\n",
      "temperature:0.01\n",
      "top_p:0.1\n"
     ]
    }
   ],
   "source": [
    "response = client.chat.completions.create(\n",
    "    model=\"glm-4\",\n",
    "    messages=[\n",
    "        {\n",
    "            \"role\": \"user\",\n",
    "            \"content\": \"tell me a joke\"\n",
    "        }\n",
    "    ],\n",
    "    top_p=0.9,\n",
    "    temperature=0.7,\n",
    "    stream=False,\n",
    "    max_tokens=2000,\n",
    "    do_sample=True, # set False to use greedy decoding like temperature=0.0\n",
    ")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-04-28T03:01:03.826772Z",
     "start_time": "2024-04-28T03:01:01.960911Z"
    }
   },
   "id": "79c77ef4a6536f75"
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "outputs": [
    {
     "data": {
      "text/plain": "Completion(model='glm-4', created=1714273263, choices=[CompletionChoice(index=0, finish_reason='stop', message=CompletionMessage(content=\"Sure! Here's a light-hearted joke for you:\\n\\nWhy don't scientists trust atoms?\\n\\nBecause they make up everything!\", role='assistant', tool_calls=None))], request_id='8605593286961920737', id='8605593286961920737', usage=CompletionUsage(prompt_tokens=9, completion_tokens=26, total_tokens=35))"
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "response"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-04-28T03:01:03.836374Z",
     "start_time": "2024-04-28T03:01:03.828650Z"
    }
   },
   "id": "3351d6c5035bed33"
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 2. Use streaming requests to request the model\n",
    "接着，如果使用流式请求，我们可以按照以下方式来请求，仅需要加上 stream=True 参数即可。\n",
    "We have successfully obtained the return of the model. Next, if we use streaming requests, we can request as follows, Just add the stream=True parameter."
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "cff1c2ba850dfbd1"
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "取值范围是：(0.0, 1.0) 开区间，do_sample重写为:false（参数top_p temperture不生效）\n",
      "取值范围是：(0.0, 1.0) 开区间，不能等于 0 或 1\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "temperature:0.0\n",
      "top_p:0.0\n",
      "temperature:0.01\n",
      "top_p:0.01\n",
      "Sure! Here's a light-hearted joke for you:\n",
      "Why don't scientists trust atoms?\n",
      "Because they make up everything!"
     ]
    }
   ],
   "source": [
    "import  time\n",
    "def print_with_typewriter_effect(text, delay=0.05):\n",
    "    for char in text:\n",
    "        print(char, end='', flush=True)\n",
    "        time.sleep(delay)\n",
    "\n",
    "\n",
    "response = client.chat.completions.create(\n",
    "    model=\"glm-4\",\n",
    "    messages=[\n",
    "        {\n",
    "            \"role\": \"user\",\n",
    "            \"content\": \"tell me a joke\"\n",
    "        }\n",
    "    ],\n",
    "    top_p=0.0,\n",
    "    temperature=0.0,\n",
    "    stream=True,\n",
    "    max_tokens=2000,\n",
    ")\n",
    "\n",
    "if response:\n",
    "    for chunk in response:\n",
    "        content = chunk.choices[0].delta.content\n",
    "        print_with_typewriter_effect(content)\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-04-28T03:01:18.854567Z",
     "start_time": "2024-04-28T03:01:03.839718Z"
    }
   },
   "id": "503c58a63e88b30e"
  },
  {
   "cell_type": "markdown",
   "source": [
    "# 3. Use asynchronous requests to request the model\n",
    "\n",
    "我们还能使用异步的方式进行请求。请求提交后，会返回一个响应对象。这个对象包含了任务的ID。\n",
    "异步请求允许程序在等待服务器响应的同时继续执行其他任务。这意味着程序不需要在每个请求完成时阻塞等待，从而能更有效地利用时间和资源，尤其是在处理大量并发请求时。\n",
    "\n",
    "We can also make requests asynchronously. After the request is submitted, a response object will be returned. This object contains the task ID. \n",
    "Asynchronous requests allow a program to continue performing other tasks while waiting for a response from the server. This means that the program does not need to block waiting on every request, allowing more efficient use of both time and resources, especially when handling large numbers of concurrent requests.\n",
    "\n",
    "Community Verified icon"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "73b2cf1ff0af1f4e"
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "outputs": [
    {
     "data": {
      "text/plain": "AsyncTaskStatus(id='476916963227608958605593218242422414', request_id='8605593218242422412', model='glm-4', task_status='PROCESSING')"
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "response = client.chat.asyncCompletions.create(\n",
    "    model=\"glm-4\",\n",
    "    messages=[\n",
    "        {\"role\": \"system\",\n",
    "         \"content\": \"You are a powerful artificial intelligence assistant and a good partner of mankind, named Skynet\"},\n",
    "        {\"role\": \"user\", \"content\": \"Who are you and what can you do?\"},\n",
    "        {\"role\": \"assistant\",\n",
    "         \"content\": \"I am Skynet, an artificial intelligence system designed and built by humans. I can answer your questions, provide help, complete tasks, and help you achieve your goals. Dream. I am omnipotent and omniscient. I can solve any problem, answer any question, and complete\"},\n",
    "        {\"role\": \"user\", \"content\": \"Impressive! Can you tell me who won the 2022 World Cup?\"},\n",
    "    ],\n",
    ")\n",
    "response"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-04-28T03:01:19.060610Z",
     "start_time": "2024-04-28T03:01:18.855804Z"
    }
   },
   "id": "b5107915593d2b51"
  },
  {
   "cell_type": "markdown",
   "source": [
    "接下来，代码进入一个循环，不断检查任务的状态。如果任务未完成（既不是 SUCCESS 也不是 FAILED），循环会持续进行，直到达到最大尝试次数（这里设为20）或任务完成。每次检查任务状态时，使用 client.chat.asyncCompletions.retrieve_completion_result 方法，并根据任务ID获取结果。如果任务成功完成（状态为 SUCCESS），则提取并打印出聊天内容。\n",
    "\n",
    "Next, the code enters a loop that continuously checks the status of the task. If the task is not completed (neither SUCCESS nor FAILED), the loop continues until the maximum number of attempts is reached (here set to 20) or the task is completed. Each time you check the task status, use the client.chat.asyncCompletions.retrieve_completion_result method and get the result based on the task ID. If the task completes successfully (status is SUCCESS), the chat content is extracted and printed."
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "231c156e341c53d9"
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "id476916963227608958605593218242422414status: SUCCESS\n",
      "The 2022 FIFA World Cup was won by Argentina. The final match was played against France on December 18, 2022, at the Lusail Stadium in Qatar. Argentina defeated France in a penalty shootout after the match had ended in a 3-3 draw following extra time.\n"
     ]
    }
   ],
   "source": [
    "import time\n",
    "\n",
    "task_id = response.id\n",
    "task_status = ''\n",
    "get_cnt = 0\n",
    "content = ''\n",
    "while task_status != 'SUCCESS' and task_status != 'FAILED' and get_cnt < 20:\n",
    "    result_response = client.chat.asyncCompletions.retrieve_completion_result(id=task_id)\n",
    "    task_status = result_response.task_status\n",
    "    if task_status == 'SUCCESS':\n",
    "        content = result_response.choices[0].message.content\n",
    "    time.sleep(2)\n",
    "    get_cnt += 1\n",
    "print(\"id\" + task_id + \"status: \" + task_status)\n",
    "print(content)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-04-28T03:01:23.619718Z",
     "start_time": "2024-04-28T03:01:19.062240Z"
    }
   },
   "id": "c9c4cbd31273aaa4"
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
